/*
 * 	Planification de trajectoires			COTTRET Mathieu et MARTIN Remi
 * 
 * 	Classe Controleur
 */

package controleur;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import modele.Ressources;
import modele.Statut;
import exception.ToutesLesUnitesBloqueesException;
import vue.Affichage;
import vue.graphique.AffichageGraphique;

public class Controleur implements Runnable {
	// Variable(s) statique(s)
	private static Controleur instance = null;
	
	// Variable(s) d'instance
	private ControleurPlateau plateau;
	private Affichage vue;
	private ControleurUnite uniteSelectionnee;
	private boolean actif;
	
	// Constructeur(s)
	private Controleur() {
		this.actif=true;
		this.vue = new AffichageGraphique();
		this.plateau = new ControleurPlateau();
		this.vue.afficher(this.plateau);
		this.uniteSelectionnee=null;
	}
	
	// Accesseur(s)
	public Affichage getVue() {
		return this.vue;
	}
	
	// Methode(s)
	public void deplacerLesUnites() {
		// Permet de deplacer les unites présentes sur le plateau
		try {
			FileInputStream fichier = new FileInputStream(new File("./fichiers/fichiers.txt"));
			BufferedReader reader = new BufferedReader(new InputStreamReader(fichier));
			
			// On choisit l'algorithme en fonction de ce qui est renseigne dans fichiers.txt
			String algorithme = reader.readLine();
			algorithme = reader.readLine();
			algorithme = reader.readLine();
			if(algorithme != null) {
				if(algorithme.equals("1")) {
					this.plateau.melangerLesTrajectoires1();
				} else {
					if(algorithme.equals("2")) {
						this.plateau.melangerLesTrajectoires2();
					} else {
						if(algorithme.equals("3")) {
							this.plateau.melangerLesTrajectoires3();
						} else {
							if(algorithme.equals("4")) {
								this.plateau.melangerLesTrajectoires4();
							}else {
								this.plateau.melangerLesTrajectoires5();
							}
						}
					}
				}
			reader.close();
			} else {
				System.out.println("Mauvais algorithme renseigné.");
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ToutesLesUnitesBloqueesException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void afficher() {
		// Actualise l'affichage
		this.vue.afficher(this.plateau);
		this.repaint();
	}
	
	@Override
	public void run() {
		// Fonction effetuée lors de l'exécution de la tache
		// Demarre les deplacements en activant/desactivant les boutons
		if(this.actif) {
			this.actif=false;
			this.vue.activationBoutons(false);
			this.deplacerLesUnites();
			this.actif=true;
			this.vue.activationBoutons(true);
			this.afficher();
		}
	}
	
	public void repaint() {
		// Actualise l'affichage
		if(this.vue instanceof AffichageGraphique) {
			AffichageGraphique vue = (AffichageGraphique) this.vue;
			vue.paint(vue.getGraphics());
		}
	}
	
	public void notification(ControleurCoordonnee arrivee) {
		// Notification de clic sur l'ecran
		// Si la zone cliquee contient une unite, alors cette unite est selectionne
		// Sinon on defini la case comme case d'arrivee de l'unite selectionne
		
		// On convertit les coordonnees reelles sur le fenetre en coordonnees sur le plateau
		ControleurCoordonnee coordonneeGrapheArrivee = new ControleurCoordonnee(arrivee.getY()/Ressources.TAILLE_CASE, 
				arrivee.getX()/Ressources.TAILLE_CASE);
		ControleurUnite unite;
		if((unite = this.plateau.unitePresenteSurCase(coordonneeGrapheArrivee)) != null) {
			this.uniteSelectionnee = unite;
			this.vue.setUniteSelectionnee(""+unite.getLabel());
		} else {
			this.definirArriveeUnite(coordonneeGrapheArrivee);
		}
	}
	
	public void definirArriveeUnite(ControleurCoordonnee arrivee) {
		// On defini une case d'arrivee a l'unite selectionnee
		
		if(this.uniteSelectionnee!= null && arrivee != null && actif) {
			// On cree les nouveaux objectifs
			ControleurObjectif objectif = new ControleurObjectif(this.uniteSelectionnee.getCoordonneeActuelle(), arrivee);
			// Avant d'affecter les nouveaux objectifs, on regarde si l'unite est arrivee
			// Si ce n'est pas le cas, on rend sa case d'arrivee accessible sur le plateau
			if(!this.uniteSelectionnee.estArrivee()) {
				ControleurCoordonnee arriveeAncienne = this.uniteSelectionnee.getObjectif().getArrivee();
				this.plateau.changerStatutCasePlateau(arriveeAncienne.getX(), arriveeAncienne.getY(), Statut.ACCESSIBLE, null);
			}
			
			// On peut maintenant affecter l'objectif
			this.plateau.definirObjectifUnite(objectif, this.uniteSelectionnee);
			
			// On actualise l'affichage
			this.afficher();
		}
	}
	
	public int nombreDUnites() {
		return this.plateau.getUnitesPresentes().size();
	}
	
	// Methode(s) statique(s)
	public static void createInstance() {
		if(Controleur.instance==null) {
			Controleur.instance = new Controleur();
		}
	}
	
	public static Controleur getInstance() {
		return Controleur.instance;
	}
}
